package io.modifier.basic.compose.hooks.time

import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import io.modifier.basic.compose.hooks.Ref
import io.modifier.basic.compose.hooks.comm.IsActive
import io.modifier.basic.compose.hooks.comm.Options
import io.modifier.basic.compose.hooks.comm.PauseFn
import io.modifier.basic.compose.hooks.comm.ResumeFn
import io.modifier.basic.compose.hooks.useMount
import io.modifier.basic.compose.hooks.useRef
import io.modifier.basic.compose.hooks.data.useState
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import io.modifier.basic.compose.hooks.utils.currentTime


/**
 * Description: [useTimestamp]和[useTimestampRef]的配置项
 *
 * @param interval the interval between timestamp changes
 * @param offset timestamp offset
 * @param callback callback
 */
@Stable
data class TimestampOptions internal constructor(
    var interval: Duration = 1.0.milliseconds,
    var offset: Duration = 0.milliseconds,
    var callback: ((Long) -> Unit)? = null,
) {
    companion object : Options<TimestampOptions>(::TimestampOptions)
}

@Composable
fun useTimestamp(optionsOf: TimestampOptions.() -> Unit = {}, autoResume: Boolean = true): TimestampHolder =
    useTimestamp(remember { TimestampOptions.optionOf(optionsOf) }, autoResume)

@Composable
fun useTimestampRef(optionsOf: TimestampOptions.() -> Unit = {}, autoResume: Boolean = true): TimestampRefHolder = useTimestampRef(
    remember { TimestampOptions.optionOf(optionsOf) },
    autoResume
)

@Stable
data class TimestampHolder(
    val state: State<Long>,
    val pause: PauseFn,
    val resume: ResumeFn,
    val isActive: IsActive,
)

@Stable
data class TimestampRefHolder(
    val ref: Ref<Long>,
    val pause: PauseFn,
    val resume: ResumeFn,
    val isActive: IsActive,
)

/**
 * Use timestamp
 *
 * @param options
 * @param autoResume If automatically execute resume when entering the component
 * @return
 */
@Composable
private fun useTimestamp(options: TimestampOptions = remember { TimestampOptions() }, autoResume: Boolean = true): TimestampHolder {
    val (interval, offset, callback) = with(options) { Triple(interval, offset, callback) }
    val timestamp = useState(default = currentTime)
    val (resume, pause, isActive) = useInterval(
        optionsOf = {
            period = interval
        }
    ) {
        timestamp.value = currentTime + offset
        callback?.invoke(timestamp.value.toEpochMilliseconds())
    }
    useMount {
        if (autoResume) resume()
    }
    val timestampState = useState { timestamp.value.toEpochMilliseconds() }
    return remember { TimestampHolder(timestampState, pause, resume, isActive) }
}

/**
 * Use timestamp ref
 *
 * @param options
 * @param autoResume If automatically execute resume when entering the component
 * @return
 */
@Composable
private fun useTimestampRef(options: TimestampOptions = remember { TimestampOptions() }, autoResume: Boolean = true): TimestampRefHolder {
    val (interval, offset, callback) = with(options) { Triple(interval, offset, callback) }
    val timestampRef = useRef(default = currentTime.toEpochMilliseconds())
    val (resume, pause, isActive) = useInterval(
        optionsOf = {
            period = interval
        }
    ) {
        timestampRef.current = (currentTime + offset).toEpochMilliseconds()
        callback?.invoke(timestampRef.current)
    }
    useMount {
        if (autoResume) resume()
    }
    return remember { TimestampRefHolder(timestampRef, pause, resume, isActive) }
}
